﻿// Arduino timer CTC interrupt example
// www.engblaze.com

// avr-libc library includes
#include <DallasTemperature.h>
#include <OneWire.h>

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>


#define OutputDisplay A3
#define AvailableAC220 2
#define OUTPUT1      3
#define OUTPUT2	     4
#define BatteryVolt  A4
#define SetButton    5
#define UpButton     6
#define DownButton   7
#define SensorPin    1
#define Piezo		A2



#define PinCommLatch  A0
#define PinClock      13
#define PinData       12

#define BatteryLed    11
#define TempLed       10
#define Term12VLed    9
#define Term200vLed   8

#define RelayOutput   A1

int led[]={BatteryLed,TempLed,Term12VLed,Term200vLed};

boolean upsState=false;
boolean upsStart=false;

int mode=0;//0=batter,1=temp,2=term12v,3=term220v

boolean enterSetupMode=false;

byte floatDigit;
const int registers = 3;
byte registerArray [registers];
byte digits [11];


int termostatTemp12V=65;
int termostatTemp220V=75;
			
boolean setTermostatTemp12V=true;
boolean settermostatTemp220V=true;

boolean updateDisplay=false;


OneWire oneWire(SensorPin);
DallasTemperature sensors(&oneWire);

unsigned long nextMillis = 0;        // will store last time LED was updated
unsigned long currentMillis;
unsigned long timeSetTemp =1500;

// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long interval = 100; 


float ATT_Volt=0;
float Voltage=0;
float R1 = 21100.0; 
float R2 = 4640.0;    
int Value=0;

int minValueV=12.1;

int loopp=0;
int looppBlinkLed=0;

long milissss=0;

boolean startInverter=false;
int timePressButton=0;
int termostatTemp=0;

float displayValue;
float currentTemp;


void setup()
{
	

	// Setup the digits array
  // a = 8 b = 4 c = 2 d = 64 e = 32 f = 1 g = 16
	digits [0] = B00000011;
	digits [1] = B00111111;
	digits [2] = B01010001;
	digits [3] = B00010101;
	digits [4] = B00101101;
	digits [5] = B10000101;
	digits [6] = B10000001;
	digits [7] = B00011111;
	digits [8] = B00000001;
	digits [9] = B00000101;
	digits[10] = B11111110;

	pinMode(OutputDisplay, OUTPUT);
	pinMode(OUTPUT1, OUTPUT);
	pinMode(OUTPUT2, OUTPUT);

	pinMode (PinCommLatch, OUTPUT);
    pinMode (PinClock, OUTPUT);
    pinMode (PinData, OUTPUT);

	pinMode(BatteryLed, OUTPUT);
	pinMode(TempLed, OUTPUT);
	pinMode(Term12VLed, OUTPUT);
	pinMode(Term200vLed, OUTPUT);

	pinMode(RelayOutput,OUTPUT);
	pinMode(AvailableAC220, INPUT_PULLUP);
	pinMode(SetButton, INPUT_PULLUP);
	pinMode(UpButton, INPUT_PULLUP);
	pinMode(DownButton, INPUT_PULLUP);

	digitalWrite(OutputDisplay,HIGH);
	readV();
	sensors.begin();
	sensors.requestTemperatures();
	currentTemp=sensors.getTempCByIndex(0);

	digitalWrite(led[mode],HIGH);
	UpdateTermostatLed();
	digitalWrite(RelayOutput,HIGH);
	UpdateDisplay();
	Start();
	
}

void loop()
{
	digitalWrite(RelayOutput,HIGH);
	if(updateDisplay)
	{
		UpdateDisplay();
		updateDisplay=false;
	}

#pragma region SetButton
	if(!digitalRead(SetButton))
	{
		WaitButton();		
		if(!digitalRead(SetButton))
		{
			if(mode<2)
			{
				NextMode();
				while(!digitalRead(SetButton))
					{
					}
			}
			else
			{
				if(enterSetupMode)
				{
			
					enterSetupMode=false;
					while(!digitalRead(SetButton))
					{
					}
					SaveChanges();
				}
				else
				{
					while(!digitalRead(SetButton))
					{
						if(nextMillis + timeSetTemp < millis())
						{
								
								enterSetupMode=true;	
								
							
						}
					}
				
					if(!enterSetupMode)
					{
			
						NextMode();
			
					}
				}		
		
						
			}
			WaitButton();		
		}
	}
#pragma endregion
	if(enterSetupMode)
	{
#pragma region UpButton
		if(!digitalRead(UpButton))
		{
				WaitButton();
				if(!digitalRead(UpButton))
				{
					if(mode==2)
					{
						termostatTemp12V+=5;
						setTermostatTemp12V=true;
						
					}
					else 
					{
						termostatTemp220V+=5;
						settermostatTemp220V=true;
						
					}
					UpdateDisplay();
					
				}
				WaitButton();
		}
#pragma endregion
#pragma region DownButton
		if(!digitalRead(DownButton))
		{
			WaitButton(); 
			if(!digitalRead(DownButton))
			{
				if(mode==2)
					{
						termostatTemp12V-=5;
						if(termostatTemp12V<=0)
						{
							termostatTemp12V=0;
							setTermostatTemp12V=false;
						}
						
					}
					else 
					{
						
						termostatTemp220V-=5;
						if(termostatTemp220V<=0)
						{	
							termostatTemp220V=0;
							settermostatTemp220V=false;
						}
					
					}
					UpdateDisplay();
				
			}
			WaitButton();
		}
		#pragma endregion
		
	}
	//if(digitalRead(AvailableAC220))//&&setTermostatTemp12V)||settermostatTemp220V
	if(true)
	{
		if(upsState==0)
		{
			readV();
			if(Voltage<minValueV)
			{
				TurnOffUps();
			}
			else 
			{
				upsState=true;
			}
			
		
			
		}

	}
	else
	{
		if(upsState==1)
		{
			TurnOffInverter();
			
		}

	}
}




void NextMode()
{
		digitalWrite(led[mode],LOW);
					if(mode==3)
					{
				
						mode=0;
				
					}
					else mode++;
				
					UpdateTermostatLed();				
					digitalWrite(led[mode],HIGH);
					UpdateDisplay();
}

	void Start()
	{
			cli();          // disable global interrupts
			TCCR1A = 0;     // set entire TCCR1A register to 0
			TCCR1B = 0;     // same for TCCR1B
			 TCNT1  = 0;//initialize counter value to 0
			// set compare match register to desired timer count:
			OCR1A = 155;

			// turn on CTC mode:
			TCCR1B |= (1 << WGM12);
			// Set CS10 and CS12 bits for 1024 prescaler:
			TCCR1B |= (1 << CS10);
			TCCR1B |= (1 << CS12);
			// enable timer compare interrupt:
			TIMSK1 |= (1 << OCIE1A);
			sei();
	}




	ISR(TIMER1_COMPA_vect)
	{
		if(upsState)
		{
			if(digitalRead(OUTPUT1))
			{
				digitalWrite(OUTPUT1,LOW);
					digitalWrite(OUTPUT2,HIGH);
			}
			else
			{
				digitalWrite(OUTPUT2,LOW);
					digitalWrite(OUTPUT1,HIGH);
			}
				
		}
		

		loopp++;
		
		if(enterSetupMode)
		{
			looppBlinkLed++;
			if(looppBlinkLed>50)
			{
				looppBlinkLed=0;
				digitalWrite(led[mode],!digitalRead(led[mode]));
			}
		}
		if(loopp>500) // 5 sec.
		{
			loopp=0;
			sensors.requestTemperatures();
			currentTemp=sensors.getTempCByIndex(0);
			readV();
			if(upsState&&Voltage<minValueV)
			{
				TurnOffUps();
			}
			
			if(mode<2)
			{
				updateDisplay=true;
			}
			
		}
	}



	

	void readV()
	{

		Value=analogRead(BatteryVolt);
		ATT_Volt=(Value*5.0)/1024.0; // 5.0 V of Vcc
		//Voltage=ATT_Volt/(R2/(R1+R2))+0.5; // Display Voltage using 7 
		Voltage=13.8;
	}

	void UpdateDisplay()
	{
		switch (mode)
		{
		case 0:
			{
				displayValue=Voltage;
				break;
			}
		case 1:
			{
				displayValue=currentTemp;
				break;  
			}
		case 2:
			{
				displayValue=termostatTemp12V;
				break;
			}
		case 3:
			{
				displayValue=termostatTemp220V;
			}
				
		}

			
		LoadValueForDisplay();
		sendSerialData(registers,registerArray);
		
	}

	

	void Stop()
	{
		TCCR1B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12));
		
	}

void 	TurnOffUps()
	{
		
		TurnOffInverter();
		digitalWrite(OutputDisplay,LOW);
		digitalWrite(RelayOutput,LOW);
		 /* Setup pin2 as an interrupt and attach handler. */
  

  
		set_sleep_mode(SLEEP_MODE_PWR_DOWN);  
		sleep_enable();
	 attachInterrupt(0, pin32Interrupt, LOW);
  
	 sleep_mode();
  
  /* The program will continue from here. */
  
  /* First thing to do is disable sleep. */
  sleep_disable(); 
			
	}

void pin32Interrupt()
{
	digitalWrite(OutputDisplay,HIGH);
}
void TurnOffInverter()
{
	
			upsState=false;
			digitalWrite(OUTPUT1, LOW);
			digitalWrite(OUTPUT2, LOW);
}
	void LoadValueForDisplay()
	{
		
		int mappedRead=0;
		if(displayValue>=100)
		{
			mappedRead=displayValue*10;
			registerArray[0] =digits[ (mappedRead/10) % 10];
			registerArray[1] =digits[ (mappedRead/100) % 10];
			registerArray[2] =digits[ (mappedRead/1000) % 10];
		}
		else 
		{
			mappedRead=displayValue*100;

			floatDigit = mappedRead % 10;
			if(floatDigit>5)
			{
				mappedRead +=10;
			}
			registerArray[0] =digits[ (mappedRead/10) % 10];
			
			registerArray[1] =digits[ (mappedRead/100) % 10]-1;//add point 
			registerArray[2] =digits[ (mappedRead/1000) % 10];
		}


	}
	void WaitButton()
	{
		nextMillis  = millis() + interval;
				while(nextMillis > millis()) 
				{		
				}
	}



void sendSerialData (byte registerCount,byte *pValueArray)  
{
 
  digitalWrite (PinCommLatch, LOW);
  
  for (byte reg = registerCount; reg > 0; reg--)
  {
    byte value = pValueArray [reg - 1];
    
    for (byte bitMask = 128; bitMask > 0; bitMask >>= 1)
    {
      digitalWrite (PinClock, LOW);
    
      digitalWrite (PinData, value & bitMask ? HIGH : LOW); 
        
      digitalWrite (PinClock, HIGH);
    }
  }
  
  digitalWrite (PinCommLatch, HIGH);
} 

void SaveChanges()
{
	digitalWrite(led[mode],HIGH);
}

void UpdateTermostatLed()
{
	
		if(mode<2)
	{
		digitalWrite(Term12VLed,setTermostatTemp12V);
		digitalWrite(Term200vLed,settermostatTemp220V);
	}
	else 
	{
		digitalWrite(Term12VLed,LOW);
		digitalWrite(Term200vLed,LOW);
	}
	

}
